/*
* @Author: 窦子滨<zibin_5257@163.com>
* @Date: 2019-04-10
 */
package TcpPack

import (
	"encoding/binary"
	"encoding/hex"
	"io"
	"strings"
)

//实时数据包
type RealTimePack struct {
	Count         int16   //数据单元个数
	DeviceStatus  int8    //单元3-设备状态
	UserId        string  //单元4-用户号或者手机号，字符串格式，20字节，小于20字节后面补0
	CarVin        string  //单元5-汽车VIN码 17字节
	ChargeVoltage float64 //单元6-充电电压 含1位小数 桩端电表读数
	ChargeCurrent float64 //单元7-充电电流 含两位小数 桩端电表读数
	ChargeTime    int32   //单元8-充电时间 单位秒
	ChargeMoney   float64 //单元9-充电金额 2位小数
	ChargeAmount  float64 //单元10-充电电能 2位小数
	SurplusTime   int32   //单元11-剩余时间 仅限直流
	Soc           int8    //单元12-当前SOC 仅限直流
	//WarnInfo      [8]byte //单元13-告警信息
	WarnPoint int32 //告警点
	WarnCause int32 //告警点原因
	CardMoney     int32   //单元14-充电卡余额 单位未知
	CardType      int8    //单元15-充电卡类型
	ChargeMethod  int8    //单元16-充电方式
	ChargeMode    int8    //单元17-充电模式
	VoltageNeed   float64 //单元18-电压需求 xxx.x 只限直流
	CurrentNeed   float64 //单元19-电流需求 xx.xx 只限直流
	ChargeVoltageDirectModel float64 //0b14-充电电压 含1位小数 直流桩充电模块输出充电电压
	ChargeCurrentDirectModel float64 //0b15-充电电流 含两位小数 直流桩充电模块输出充电电流
	SumMoney float64
	ServiceMoney float64
	BeforeSoc int16 //0b1a 整车动力蓄电池荷电状态（充电前的SOC）
}

//接收到实时数据包后的回应
type RealTimeReplyPack struct {
	Count   int16 //数据单元个数
	Confirm int8  //确认标识 1-确认
}

//回应数据编码
func (p *RealTimeReplyPack) Pack(writer io.Writer) error {
	var err error
	err = binary.Write(writer, binary.LittleEndian, &p.Count)
	err = binary.Write(writer, binary.LittleEndian, &p.Confirm)
	return err
}

//实时数据解码
func (p *RealTimePack) Unpack(reader io.Reader) error {
	var err error
	//数据单元个数
	err = binary.Read(reader, binary.LittleEndian, &p.Count)

	var b [2]byte   //数据单元标识
	var l int8      //数据单元长度
	var mark string //标识字符串
	var n int32     //用于读取通用的金额字段
	//var bcd [7]byte //bcd 7字节数据

	var temp []byte //临时变长byte数据
	for i := 0; i < int(p.Count); i++ {
		err = binary.Read(reader, binary.LittleEndian, &b)
		mark = hex.EncodeToString(b[:])
		err = binary.Read(reader, binary.LittleEndian, &l)
		//根据指令选择处理方式
		switch mark {
		case "0306", "0406": //未知数据
			temp = make([]byte, l)
			err = binary.Read(reader, binary.LittleEndian, &temp)
		case "010B", "010b": //设备状态
			err = binary.Read(reader, binary.LittleEndian, &p.DeviceStatus)
		case "020B", "020b":
			var u [20]byte
			err = binary.Read(reader, binary.LittleEndian, &u)
			p.UserId = strings.ReplaceAll(string(u[:]),"\x00","")
			//num,_:=strconv.ParseInt(s,16,64)
			//p.UserId = num
		case "030B", "030b": //车辆vin
			var v [17]byte
			err = binary.Read(reader, binary.LittleEndian, &v)
			p.CarVin=strings.ReplaceAll(string(v[:]),"\x00","")
		case "040B", "040b": //充电电压
			err = binary.Read(reader, binary.LittleEndian, &n)
			p.ChargeVoltage = float64(n) / 10
		case "050B", "050b": //充电电流
			err = binary.Read(reader, binary.LittleEndian, &n)
			p.ChargeCurrent = float64(n) / 100
		case "060B", "060b": //充电时间
			err = binary.Read(reader, binary.LittleEndian, &p.ChargeTime)
		case "070B", "070b": //充电金额
			err = binary.Read(reader, binary.LittleEndian, &n)
			p.ChargeMoney = float64(n) / 100
		case "080B","080b": //充电电能
			err = binary.Read(reader, binary.LittleEndian, &n)
			p.ChargeAmount = float64(n) / 100
		case "090B", "090b": //剩余时间
			err = binary.Read(reader, binary.LittleEndian, &p.SurplusTime)
		case "0A0B", "0a0b": //当前soc
			err = binary.Read(reader, binary.LittleEndian, &p.Soc)
		case "0B0B", "0b0b": //告警信息
			err = binary.Read(reader, binary.LittleEndian, &p.WarnPoint)
			err = binary.Read(reader, binary.LittleEndian, &p.WarnCause)
		case "0C0B", "0c0b": //充电卡余额
			err = binary.Read(reader, binary.LittleEndian, &p.CardMoney)
		case "0D0B", "0d0b": //充电卡类型
			err = binary.Read(reader, binary.LittleEndian, &p.CardType)
		case "0E0B", "0e0b": //充电方式
			err = binary.Read(reader, binary.LittleEndian, &p.ChargeMethod)
		case "0F0B", "0f0b": //充电模式
			err = binary.Read(reader, binary.LittleEndian, &p.ChargeMode)
		case "100B", "100b": //电压需求
			err = binary.Read(reader, binary.LittleEndian, &n)
			p.VoltageNeed = float64(n) / 10
		case "110B", "110b": //电流需求
			err = binary.Read(reader, binary.LittleEndian, &n)
			p.CurrentNeed = float64(n) / 100
		case "140B", "140b": //充电电压 直流桩模块输出 1位小数
			err = binary.Read(reader, binary.LittleEndian, &n)
			p.ServiceMoney = float64(n) / 100
		case "150B", "150b": //充电电流 直流桩模块输出 2位小数
			err = binary.Read(reader, binary.LittleEndian, &n)
			p.SumMoney = float64(n) / 100
		case "1a0b":
			err = binary.Read(reader, binary.LittleEndian, &p.BeforeSoc)
		default:
			temp = make([]byte, l)
			err = binary.Read(reader, binary.LittleEndian, &temp)
		}
	}

	return err
}
